import copy
import ast
from PySide2.QtWidgets import (
    QTableWidget,
    QVBoxLayout,
    QWidget,
    QSizePolicy,
    QComboBox,
    QHeaderView,
    QStyledItemDelegate,
    QTableWidgetItem,
    QLineEdit,
    QMenu,
    QApplication,
)
from PySide2.QtCore import Signal, Qt, QEvent
from PySide2.QtGui import (
    QPainter,
    QPen,
    QColor,
    QDoubleValidator,
    QIntValidator,
    QCursor,
    QFocusEvent,
)
from PySide2.QtCore import QTimer
from functools import partial

# from ui_style import UiStyle
from .. import message_box as MBox
from ..utils import Utils
from ..custom_widget import SelectBox, CustomCellComboBoxMultiSelectStr
from ..params_table import ParamsTable, CustomTableWidgetItem


# 新增行必须使用 addRow()
class MaterialTable(ParamsTable):

    def __init__(self, rows=0, columns=2, isLibrary=False, parent=None):
        super(MaterialTable, self).__init__(rows, columns, isLibrary, parent)
        self.idCloumn = 0

    def add(self):
        lastRow = self.selectedLastRow()
        if lastRow < 0:
            lastRow = -1
        elif lastRow == self.rowCount() - 1:
            lastRow = -1
        else:
            lastRow = lastRow + 1
        self.addRow(row=lastRow, isAddIncrementing=True)

    def addRow(self, row=-1, rowData=[], isAddIncrementing=False, isPastOrImport=False):
        row_position = row
        if row < 0:
            row_position = self.rowCount()
        self.insertRow(row_position)
        previousItem = None
        if row_position > 0:
            previousItem = self.item(row_position - 1, 0)
        for column in range(self.columnCount()):
            item = CustomTableWidgetItem("")
            if column in self.rowDoubleClick:
                item.setFlags(item.flags() & ~Qt.ItemIsEditable)
            # 判断是否有数据
            if rowData and not all(x is None or x == "" for x in rowData):
                if len(rowData) > column:
                    formatValue = self.getRuleValueToStr(rowData[column], column)
                    if column == 0:
                        # 判断是否自增id
                        if (rowData[0] == None or rowData[0] == "") and isAddIncrementing:
                            if previousItem:
                                previousId = Utils.toIntOrNone(previousItem.text())
                                if previousId is not None:
                                    item.setText(str(previousId + 1))
                            else:
                                item.setText("1")
                        else:
                            item.setText(formatValue)
                    else:
                        if item.getReadyOnly() == False:
                            item.setText(formatValue)
                    if (
                        isPastOrImport
                        and formatValue == ""
                        and not (not rowData[column] and rowData[column] != 0)
                    ):
                        self.incorrectFormatRowList.append(row_position)
            else:
                if isAddIncrementing:
                    if column == 0:
                        if previousItem:
                            previousId = Utils.toIntOrNone(previousItem.text())
                            # 判断上一个id是否为空并且不能是插入而是新增
                            if previousId is not None and row == -1:
                                item.setText(str(previousId + 1))
                        else:
                            item.setText("1")
            self.setItem(row_position, column, item)

    # 末尾插入多行，并设置数据
    def addMulitRows(self, rowsData=[], isAddIncrementing=False, isPastOrImport=False):
        for rowData in rowsData:
            self.addRow(
                rowData=rowData,
                isAddIncrementing=isAddIncrementing,
                isPastOrImport=isPastOrImport,
            )

    # 填充指定行数据
    def fillRowData(self, row, rowData, isPastOrImport=False):
        if not rowData:
            return
        totalColumn = self.columnCount()
        if rowData and isinstance(rowData, list):
            for column, data in enumerate(rowData):
                if column >= totalColumn:
                    break
                item = self.item(row, column)
                formatValue = self.getRuleValueToStr(data, column)
                if item is None:
                    item = CustomTableWidgetItem()
                    if not (isPastOrImport and formatValue == ""):
                        item.setText(formatValue)
                    else:
                        item.setText("")
                    self.setItem(row, column, item)
                else:
                    if item.getReadyOnly() == False:
                        if not (isPastOrImport and formatValue == ""):
                            item.setText(formatValue)
                        else:
                            item.setText("")
                # 判断是否有格式错误
                if isPastOrImport and formatValue == "" and not (not data and data != 0):
                    self.incorrectFormatRowList.append(row)

    def getTableDictList(self):
        nameDict = {}
        idDict = {}
        for row in range(self.rowCount()):
            rowData = self.getRowData(row)
            if rowData:
                if rowData[1] != "" and rowData[1] is not None:
                    nameDict[str(rowData[1])] = {"content": rowData, "row": row}
                if rowData[0] != "" and rowData[0] is not None:
                    idDict[str(rowData[0])] = {"content": rowData, "row": row}
        return [nameDict, idDict]

    # 更新指定单元格的数据
    def updateCellData(self, row, col, value, isPastOrImport=False):
        item = self.item(row, col)
        formatValue = self.getRuleValueToStr(value, col)
        if item is None:
            item = CustomTableWidgetItem()
            if not (isPastOrImport and formatValue == ""):
                item.setText(formatValue)
            else:
                item.setText("")
            self.setItem(row, col, item)
        if item.getReadyOnly() == False:
            # if Utils.toIntOrNone(value) is None:
            #     return
            if not (isPastOrImport and formatValue == ""):
                item.setText(formatValue)
            else:
                item.setText("")

        # 判断是否有格式错误
        if isPastOrImport and formatValue == "" and not (not value and value != 0):
            self.incorrectFormatRowList.append(row)

    def nameCellChange(self, row, col):
        if self.current_edit_row == -1 or self.current_edit_col == -1:
            return
        if col != self.uniqueFlagColumn and col != self.idCloumn:
            return
        if row == self.current_edit_row and col == self.current_edit_col:
            item = self.item(row, col)
            hint = "id重复！"
            if col == 1:
                hint = "名称重复！"
            isDuplicate = self.value_is_duplicate(col=col, curItem=item, hint=hint)
            if not isDuplicate:
                self.sortTableByID()
            self.current_edit_row = -1
            self.current_edit_col = -1

    def paste_tb_text(self):
        self.incorrectFormatRowList = []
        try:
            text = QApplication.clipboard().text()
            pasteList = text.split("\n")
            # 复制后，尾部会有一个空字符串数组，需要去掉
            if len(pasteList) > 0:
                if pasteList[-1] == "":
                    pasteList.pop(-1)
            pasteList2D = []
            for row in pasteList:
                pasteList2D.append(row.split("\t"))
            rows = len(pasteList)
            isMutli = self.isMutli(pasteList2D)
            indexes = self.selectedIndexes()
            if indexes:
                # 选中单元后粘贴
                for index in indexes:
                    index = index
                    break
                r, c = index.row(), index.column()  # 拿到选中的第一个单元格
                residueColumn = self.columnCount() - c
                if residueColumn < len(pasteList2D[0]):
                    isPaste = MBox.confirm(
                        f"粘贴数据包含{len(pasteList2D[0])}列，但表格仅剩{residueColumn}列，超出部分不会被粘贴。是否继续？",
                    )
                    if isPaste:
                        self.seletedToPaste(isMutli, rows, r, c, pasteList2D, indexes ,text)
                else:
                    self.seletedToPaste(isMutli, rows, r, c, pasteList2D, indexes ,text)
                                
            else:
                # 直接粘贴
                sameNameDict = {}
                sameIdeDict = {}
                # 判断数据是否有id
                hasId = True
                if Utils.toInt(pasteList2D[0][0]) == "":
                    # 没有id
                    hasId = False

                if self.uniqueFlagColumn != -1:
                    if not hasId:
                        pasteList2D = [[""] + sublist for sublist in pasteList2D]
                    copyData = pasteList2D.copy()
                    # 分别拿到name和id对应的字典列表
                    [nameDict, idDict] = self.getTableDictList()
                    for addIndex in range(len(copyData) - 1, -1, -1):  # 倒序遍历
                        csvRow = copyData[addIndex]
                        # 更新同名
                        if (
                            len(csvRow) > 2
                            and csvRow[1] is not None
                            and str(csvRow[1]) in nameDict
                        ):
                            sameNameDict[nameDict[str(csvRow[1])]["row"]] = csvRow
                            del pasteList2D[addIndex]
                            continue
                        # 更新同id
                        if csvRow[0] is not None and str(csvRow[0]) in idDict:
                            sameIdeDict[idDict[str(csvRow[0])]["row"]] = csvRow
                            del pasteList2D[addIndex]
                            continue
                    self.addMulitRows(
                        pasteList2D, isAddIncrementing=True, isPastOrImport=True
                    )
                    # else:
                    #     # 更新同名
                    #     if (
                    #         len(csvRow) > 1
                    #         and csvRow[0] is not None
                    #         and str(csvRow[0]) in nameDict
                    #     ):
                    #         sameNameDict[nameDict[str(csvRow[0])]["row"]] = csvRow
                    #         del pasteList2D[addIndex]
                    #         continue

                    #     self.addMulitRows(
                    #         pasteList2D, isAddIncrementing=True, isPastOrImport=True
                    #     )
                    if len(sameIdeDict) > 0:
                        isIdSame = MBox.confirm(
                            text=f"目标包含{str(len(sameIdeDict))}个相同id的数据!",
                            title="替换或跳过",
                            sureText="替换",
                            cancelText="跳过",
                        )
                        if isIdSame:
                            for row, value in sameIdeDict.items():
                                self.updateRowData(row, value, True)
                    if len(sameNameDict) > 0:
                        isNameSame = MBox.confirm(
                            text=f"目标包含{str(len(sameNameDict))}个相同名称的数据!",
                            title="替换或跳过",
                            sureText="替换",
                            cancelText="跳过",
                        )
                        if isNameSame:
                            for row, value in sameNameDict.items():
                                self.updateRowData(row, value, True)

                else:
                    self.addMulitRows(pasteList2D, isPastOrImport=True)
            self.sortTableByID()
            if len(self.incorrectFormatRowList) > 0:
                MBox.warning(
                    text=f"数据格式不正确!",
                )
                self.incorrectFormatRowList = []
        except Exception as e:
            print(e)
            return
        
    def seletedToPaste(self, isMutli, rows, r, c, pasteList2D, indexes ,text):
        text = text.replace('\n', '')
        if isMutli:
            # 粘贴多个
            if self.uniqueFlagColumn != -1:
                # 粘贴从第一列开始
                # if c == 0:
                #     copyData = pasteList2D.copy()
                #     tableDict = self.getTableDict()
                #     for addIndex in range(
                #         len(copyData) - 1, -1, -1
                #     ):  # 倒序遍历
                #         csvRow = copyData[addIndex]
                #         if (
                #             csvRow[self.uniqueFlagColumn] is not None
                #             and str(csvRow[self.uniqueFlagColumn]) in tableDict
                #         ):
                #             self.updateRowData(
                #                 tableDict[str(csvRow[self.uniqueFlagColumn])][
                #                     "row"
                #                 ],
                #                 csvRow,
                #                 True,
                #             )
                #             del pasteList2D[addIndex]
                #     self.addMulitRows(pasteList2D, isPastOrImport=True)
                # else:
                # 粘贴不从第一列开始，暂时都使用这个
                for addRow in range(rows):
                    # 拿到真实的row
                    row = addRow + r
                    if row > self.rowCount() - 1:
                        # 新增行
                        rowData = [None] * self.columnCount()
                        rowData[c : c + len(pasteList2D[addRow])] = (
                            pasteList2D[addRow]
                        )
                        self.addRow(row, rowData, isPastOrImport=True)
                    else:
                        # 修改行
                        rowData = self.getRowData(row)
                        rowData[c : c + len(pasteList2D[addRow])] = (
                            pasteList2D[addRow]
                        )
                        self.fillRowData(row, rowData, True)
            else:
                # 第一列的值不唯一
                for addRow in range(rows):
                    # 拿到真实的row
                    row = addRow + r
                    if row > self.rowCount() - 1:
                        # 新增行
                        rowData = [None] * self.columnCount()
                        rowData[c : c + len(pasteList2D[addRow])] = (
                            pasteList2D[addRow]
                        )
                        self.addRow(row, rowData, isPastOrImport=True)
                    else:
                        # 修改行
                        rowData = self.getRowData(row)
                        rowData[c : c + len(pasteList2D[addRow])] = (
                            pasteList2D[addRow]
                        )
                        self.fillRowData(row, rowData, True)
        else:
            # 单个 复制单个单元或值，粘贴到所有选中的单元格中
            for index in indexes:
                # if (
                #     self.uniqueFlagColumn == index.column()
                #     or 0 == index.column()
                # ):
                #     # TODO这里暂时禁止复制，后续可继续优化处理
                #     continue
                self.updateCellData(
                    index.row(),
                    index.column(),
                    text,
                    isPastOrImport=True,
                )
                
    # def getRowData(self, row):
    #     dataList = []
    #     if row > self.rowCount() - 1:
    #         return None
    #     for col in range(self.columnCount()):
    #         item = self.item(row, col)
    #         if item is not None:
    #             if col in self.rowList:
    #                 try:
    #                     if not item.text():
    #                         dataList.append([])
    #                     else:
    #                         array = ast.literal_eval(item.text())
    #                         if isinstance(array, list):
    #                             dataList.append(array)
    #                         else:
    #                             dataList.append([])
    #                 except (ValueError, SyntaxError) as e:
    #                     dataList.append([])
    #                     print(f"解析错误: {e}")
    #             else:
    #                 dataList.append(self.getRuleValue(item.text(), col))
    #         else:
    #             dataList.append(None)
    #     return [] if all(x == "" for x in dataList) else dataList
    
    def getRowDataCheck(self, row):
        dataList = []
        if row > self.rowCount() - 1:
            return None
        for col in range(self.columnCount()):
            item = self.item(row, col)
            if item is not None:
                value = self.getRuleValue(item.text().strip(), col)
                if value == "" or value is None:
                    return None
                else:
                    dataList.append(value)
            else:
                return None
        return [] if all(x == "" for x in dataList) else dataList
    
    # def getRowData(self, row):
    #     dataList = []
    #     if row > self.rowCount() - 1:
    #         return None
    #     for col in range(self.columnCount()):
    #         item = self.item(row, col)
    #         if item is not None:
    #             dataList.append(self.getRuleValue(item.text(), col))
    #         else:
    #             dataList.append(None)
    #     return [] if all(x == "" for x in dataList) else dataList

    def getTableDictFirstNoNull(self):
        idDict = {}
        nameDict = {}
        for row in range(self.rowCount()):
            rowData = self.getRowDataCheck(row)
            if not rowData:
                MBox.warning(f"表格中存在未填写的内容，请填写完整数据后再保存!")
                return False
            # 判断是否为空，空返回int
            if rowData[0] == "" or rowData[0] is None:
                MBox.warning(f"第{str(row+1)}行id不可为空!")
                return row + 1
            if rowData[1] == "" or rowData[1] is None:
                MBox.warning(f"第{str(row+1)}行名称不可为空!")
                return row + 1
            # 判断是否重复，重复返回str
            if str(rowData[0]) in idDict:
                MBox.warning(f"第{str(row+1)}行ID已存在!")
                return str(row + 1)
            if str(rowData[1]) in nameDict:
                MBox.warning(f"第{str(row+1)}行名称已存在!")
                return str(row + 1)
            idDict[str(rowData[0])] = rowData
            nameDict[str(rowData[1])] = rowData
        return nameDict
    
    def validate_table_data(self):
        dict = {}
        keyCol = 0 if self.uniqueFlagColumn == -1 else self.uniqueFlagColumn
        for row in range(self.rowCount()):
            rowData = self.getRowDataCheck(row)
            if not rowData:
                return False
            else:
                # # 判断是否为空，空返回int
                # if rowData[keyCol] == "" or rowData[keyCol] is None:
                #     return row + 1
                # 判断是否重复，重复返回str
                if str(rowData[keyCol]) in dict:
                    return str(row + 1)
                
                
                dict[str(rowData[keyCol])] = rowData
        return dict


